package cn.kgc.tangcco.rest;

import cn.binarywang.tools.generator.ChineseNameGenerator;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.kgc.tangcco.model.ResposeText;
import cn.kgc.tangcco.model.ResultCode;
import cn.kgc.tangcco.pojo.Person;
import cn.kgc.tangcco.utils.date.BaseDateUtil;
import com.alibaba.fastjson.JSON;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.FormDataParam;

import javax.servlet.ServletContext;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

/**
 * @author 李昊哲
 * @Description
 * @create 2020/10/8 17:01
 */
@Path(value = "/person")
@Produces(MediaType.APPLICATION_JSON)
public class PersonRest {
    private static List<Person> list = new ArrayList<>();

    static {
        Long min = 630720000000L;
        Long max = 946080000000L;
        for (int i = 0; i < 10000; i++) {
            long time = System.currentTimeMillis();
            time -= RandomUtil.randomLong(min, max);
            Date date = new Date();
            date.setTime(time);
            list.add(new Person(i + 1, ChineseNameGenerator.getInstance().generate(), date));
        }
        // list.forEach(person -> System.out.println(JSON.toJSONString(person)));
    }

    @GET
    @Path(value = "/list")
    public List<Person> list() {
        return list;
    }

    @GET
    @Path(value = "/getPersonById/{id}")
    public Person getPersonById(@PathParam("id") int id) {
        List<Person> personList = list.stream().filter(person -> person.getId() == id).collect(Collectors.toList());
        if (personList != null && personList.size() > 0) {
            return personList.get(0);
        }
        return null;
    }

    @GET
    @Path(value = "/findPersonsByBirthdayWithFormOfGet")
    public List<Person> findPersonsByBirthdayWithFormOfGet(@QueryParam("startBirthday") String startBirthday, @QueryParam("endBirthday") String endBirthday) throws ParseException {
        var ref = new Object() {
            Date from = BaseDateUtil.parse(startBirthday, "yyyy-MM-dd");
            Date to = BaseDateUtil.parse(endBirthday, "yyyy-MM-dd");
        };
        if (ref.from.after(ref.to)) {
            Date temp = ref.from;
            ref.from = ref.to;
            ref.to = temp;
        }
        // 从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量
        List<Person> personList = list.stream().filter(person -> person.getBirthday().after(ref.from) && person.getBirthday().before(ref.to)).sorted(Comparator.comparing(Person::getBirthday).reversed()).collect(Collectors.toList());
        if (personList != null && personList.size() > 0) {
            return personList;
        }
        return new ArrayList<Person>();
    }

    @POST
    @Path(value = "/findPersonsByBirthdayWithFormOfPost")
    @Consumes(value = MediaType.APPLICATION_FORM_URLENCODED)
    public List<Person> findPersonsByBirthdayWithFormOfPost(@FormParam("startBirthday") String startBirthday, @FormParam("endBirthday") String endBirthday) throws ParseException {
        var ref = new Object() {
            Date from = BaseDateUtil.parse(startBirthday, "yyyy-MM-dd");
            Date to = BaseDateUtil.parse(endBirthday, "yyyy-MM-dd");
        };
        if (ref.from.after(ref.to)) {
            Date temp = ref.from;
            ref.from = ref.to;
            ref.to = temp;
        }
        // 从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量
        List<Person> personList = list.stream().filter(person -> person.getBirthday().after(ref.from) && person.getBirthday().before(ref.to)).sorted(Comparator.comparing(Person::getBirthday).reversed()).collect(Collectors.toList());
        if (personList != null && personList.size() > 0) {
            return personList;
        }
        return new ArrayList<Person>();
    }

    @POST
    @Path(value = "/findPersonsByBirthdayWithForm")
    @Consumes(value = MediaType.APPLICATION_FORM_URLENCODED)
    public Map<String, Object> findPersonsByBirthdayWithForm(@FormParam("startBirthday") String startBirthday, @FormParam("endBirthday") String endBirthday, @QueryParam("page") int page, @QueryParam("limit") int limit) throws ParseException {
        var ref = new Object() {
            Date from = BaseDateUtil.parse(startBirthday, "yyyy-MM-dd");
            Date to = BaseDateUtil.parse(endBirthday, "yyyy-MM-dd");
        };
        if (ref.from.after(ref.to)) {
            Date temp = ref.from;
            ref.from = ref.to;
            ref.to = temp;
        }
        int fromIndex = (page - 1) * limit;
        int toIndex = page * limit;
        // 从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量
        List<Person> personList = list.stream().filter(person -> person.getBirthday().after(ref.from) && person.getBirthday().before(ref.to)).sorted(Comparator.comparing(Person::getBirthday).reversed()).collect(Collectors.toList());
        Map<String, Object> map = new ConcurrentHashMap<>();
        map.put("code", 0);
        map.put("msg", "");
        map.put("count", 0);
        map.put("data", new ArrayList<Person>());
        if (personList != null && personList.size() > 0) {
            map.put("count", personList.size());
            map.put("data", personList.subList(fromIndex, toIndex));
        }
        return map;
    }

    @POST
    @Path(value = "/findPersonsByBirthdayWithJson")
    @Consumes(value = MediaType.APPLICATION_JSON)
    public Map<String, Object> findPersonsByBirthdayWithJson(Map<String, String> paramsMap, @QueryParam("page") int page, @QueryParam("limit") int limit) throws ParseException {

        var ref = new Object() {
            Date from = BaseDateUtil.parse(paramsMap.get("startBirthday"), "yyyy-MM-dd");
            Date to = BaseDateUtil.parse(paramsMap.get("endBirthday"), "yyyy-MM-dd");
        };

        if (ref.from.after(ref.to)) {
            Date temp = ref.from;
            ref.from = ref.to;
            ref.to = temp;
        }

        int fromIndex = (page - 1) * limit;
        int toIndex = page * limit;
        // 从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量
        List<Person> personList = list.stream().filter(person -> person.getBirthday().after(ref.from) && person.getBirthday().before(ref.to)).sorted(Comparator.comparing(Person::getBirthday).reversed()).collect(Collectors.toList());
        Map<String, Object> map = new ConcurrentHashMap<>();
        map.put("code", 0);
        map.put("msg", "");
        map.put("count", 0);
        map.put("data", new ArrayList<Person>());
        if (personList != null && personList.size() > 0) {
            map.put("count", personList.size());
            map.put("data", personList.subList(fromIndex, toIndex));
        }
        return map;
    }

    @POST
    @Path(value = "/findPersonsByBirthdayWithMap")
    @Consumes(value = MediaType.APPLICATION_FORM_URLENCODED)
    public Map<String, Object> findPersonsByBirthdayWithMap(MultivaluedMap<String, String> paramsMap, @QueryParam("page") int page, @QueryParam("limit") int limit) throws ParseException {

        var ref = new Object() {
            Date from = BaseDateUtil.parse(paramsMap.get("startBirthday").get(0), "yyyy-MM-dd");
            Date to = BaseDateUtil.parse(paramsMap.get("endBirthday").get(0), "yyyy-MM-dd");
        };

        if (ref.from.after(ref.to)) {
            Date temp = ref.from;
            ref.from = ref.to;
            ref.to = temp;
        }

        int fromIndex = (page - 1) * limit;
        int toIndex = page * limit;
        // 从lambda 表达式引用的本地变量必须是最终变量或实际上的最终变量
        List<Person> personList = list.stream().filter(person -> person.getBirthday().after(ref.from) && person.getBirthday().before(ref.to)).sorted(Comparator.comparing(Person::getBirthday).reversed()).collect(Collectors.toList());
        Map<String, Object> map = new ConcurrentHashMap<>();
        map.put("code", 0);
        map.put("msg", "");
        map.put("count", 0);
        map.put("data", new ArrayList<Person>());
        if (personList != null && personList.size() > 0) {
            map.put("count", personList.size());
            map.put("data", personList.subList(fromIndex, toIndex));
        }
        return map;
    }

    @PUT
    @Path(value = "/putPersonWithForm")
    @Consumes(value = MediaType.APPLICATION_FORM_URLENCODED)
    public Person putPersonWithForm(@FormParam("name") String name, @FormParam("birthday") String birthday) throws ParseException {
        return new Person(33, name, BaseDateUtil.parse(birthday, "yyyy-MM-dd"));
    }

    @PUT
    @Path(value = "/putPersonWithJson")
    @Consumes(value = MediaType.APPLICATION_JSON)
    public Person putPersonWithJson(Person person) {
        person.setId(66);
        return person;
    }

    @DELETE
    @Path(value = "/delPersonById/{id}")
    public ResposeText delPersonById(@PathParam("id") int id) {
        list.forEach(person -> System.out.println(JSON.toJSONString(person)));
        if (list.removeIf(person -> person.getId() == id)) {
            System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++");
            list.forEach(person -> System.out.println(JSON.toJSONString(person)));
            ResultCode success = ResultCode.SUCCESS;
            return new ResposeText(success.getCode(), success.getMsg(), null);
        }
        ResultCode failed = ResultCode.FAILED;
        return new ResposeText(failed.getCode(), failed.getMsg(), null);
    }

    @POST
    @Path(value = "/upload01")
    @Consumes(value = MediaType.MULTIPART_FORM_DATA)
    public ResposeText upload01(@FormDataParam("header") InputStream source,
                                @FormDataParam("header") FormDataContentDisposition disposition,
                                @Context ServletContext context) throws IOException {
        String name = disposition.getName();
        System.out.println("表单name的值>>>" + name);
        // 获取文件原始名称
        String originalFilename = disposition.getFileName();
        // 获取服务器在文件系统的真实路径
        String serverRootPath = context.getRealPath("/");
        //  ContetxtPath
        String contetxtPath = "/statics/upload/";
        // 使用时间自动创建目录
        String formatter = BaseDateUtil.format(new Date(), "yyyy/MM/dd/HH/");
        // 文件被上传的路径
        String uploadPath = serverRootPath + contetxtPath + formatter;
        //获得源文件后缀
        String suffix = FilenameUtils.getExtension(originalFilename);
        // 新文件名字
        String newFileName = IdUtil.fastSimpleUUID() + "." + suffix;
        System.out.println(newFileName);
        File file = new File(uploadPath);
        if (!file.exists()) {
            // 上传目录不存在则创建该目录
            file.mkdirs();
        }
        // 目标文件
        File destination = new File(uploadPath, newFileName);
        try {
            // 文件复制 保存文件
            FileUtils.copyInputStreamToFile(source, destination);
            ResultCode success = ResultCode.SUCCESS;
            return new ResposeText(success.getCode(), success.getMsg(), contetxtPath + formatter + newFileName);
        } catch (Exception e) {
            ResultCode failed = ResultCode.FAILED;
            return new ResposeText(failed.getCode(), failed.getMsg(), null);
        }
    }

    @POST
    @Path(value = "/upload02")
    @Consumes(value = MediaType.MULTIPART_FORM_DATA)
    public ResposeText upload02(FormDataMultiPart form,
                                @Context ServletContext context) throws IOException {
        FormDataBodyPart part = form.getField("header");
        String name = part.getName();
        System.out.println("表单name的值>>>" + name);
        // 获取源文件
        FormDataContentDisposition disposition = part.getFormDataContentDisposition();
        // 获取文件原始名称
        String originalFilename = disposition.getFileName();
        // 获取服务器在文件系统的真实路径
        String serverRootPath = context.getRealPath("/");
        //  ContetxtPath
        String contetxtPath = "/statics/upload/";
        // 使用时间自动创建目录
        String formatter = BaseDateUtil.format(new Date(), "yyyy/MM/dd/HH/");
        // 文件被上传的路径
        String uploadPath = serverRootPath + contetxtPath + formatter;
        //获得源文件后缀
        String suffix = FilenameUtils.getExtension(originalFilename);
        // 新文件名字
        String newFileName = IdUtil.fastSimpleUUID() + "." + suffix;
        System.out.println(newFileName);
        File file = new File(uploadPath);
        if (!file.exists()) {
            // 上传目录不存在则创建该目录
            file.mkdirs();
        }
        // 目标文件
        File destination = new File(uploadPath, newFileName);
        try {
            // 文件复制 保存文件
            FileUtils.copyInputStreamToFile(part.getValueAs(InputStream.class), destination);
            ResultCode success = ResultCode.SUCCESS;
            return new ResposeText(success.getCode(), success.getMsg(), contetxtPath + formatter + newFileName);
        } catch (Exception e) {
            ResultCode failed = ResultCode.FAILED;
            return new ResposeText(failed.getCode(), failed.getMsg(), null);
        }
    }

    @GET
    @Path(value = "/getHeaderParam")
    public ResposeText getHeaderParam(@HeaderParam("mobile") String mobile) {
        return new ResposeText(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), mobile);
    }

    @GET
    @Path(value = "/getCookie")
    public ResposeText getCookie(@CookieParam("mobile") String mobile) {
        return new ResposeText(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), mobile);
    }
}
